From 6eb6827927def6eb19bdfb3232561759facc466f Mon Sep 17 00:00:00 2001 From: robertl Date: Tue, 1 Apr 2003 03:21:24 +0000 Subject: [PATCH] Add route handling for magproto, mapsend, GPX. Thanx, Alex Mottram! --- gpsbabel/defs.h | 4 + gpsbabel/gpx.c | 135 ++++++++++++++-- gpsbabel/magellan.h | 1 + gpsbabel/magproto.c | 205 +++++++++++++++++++++---- gpsbabel/mapsend.c | 157 ++++++++++++++++++- gpsbabel/reference/route/magellan.rte | 22 +++ gpsbabel/reference/route/route.gpx | 77 ++++++++++ gpsbabel/reference/route/route.mapsend | Bin 0 -> 922 bytes gpsbabel/route.c | 17 ++ gpsbabel/testo | 27 ++++ gpsbabel/waypt.c | 20 +++ 11 files changed, 620 insertions(+), 45 deletions(-) create mode 100644 gpsbabel/reference/route/magellan.rte create mode 100644 gpsbabel/reference/route/route.gpx create mode 100644 gpsbabel/reference/route/route.mapsend diff --git a/gpsbabel/defs.h b/gpsbabel/defs.h index f6042da7e..5107b2dc5 100644 --- a/gpsbabel/defs.h +++ b/gpsbabel/defs.h @@ -168,6 +168,7 @@ typedef struct { char *rte_name; char *rte_desc; int rte_num; + int rte_waypt_ct; /* # waypoints in waypoint list */ } route_head; typedef void (*ff_init) (char const *, char const *); @@ -193,6 +194,7 @@ typedef void (*waypt_cb) (const waypoint *); typedef void (*route_hdr)(const route_head *); typedef void (*route_trl)(const route_head *); void waypt_add (waypoint *); +waypoint * waypt_dupe (waypoint *); void waypt_del (waypoint *); void waypt_free (waypoint *); void waypt_disp_all(waypt_cb); @@ -208,6 +210,8 @@ void route_disp_all(route_hdr, route_trl, waypt_cb); void route_free (route_head *); void route_flush( queue *); void route_flush_all(); +unsigned int route_waypt_count(void); +unsigned int route_count(void); /* * All shortname functions take a shortname handle as the first arg. diff --git a/gpsbabel/gpx.c b/gpsbabel/gpx.c index e79349124..133850d89 100644 --- a/gpsbabel/gpx.c +++ b/gpsbabel/gpx.c @@ -24,6 +24,7 @@ static int in_wpt; static int in_rte; +static int in_rtept; static int in_trk; static int in_trkpt; static int in_ele; @@ -66,6 +67,7 @@ static time_t file_time; static char *gsshortnames = NULL; static route_head *trk_head; +static route_head *rte_head; #define MYNAME "GPX" #define MY_CBUF 4096 @@ -296,8 +298,13 @@ gpx_start(void *data, const char *el, const char **attr) else if (strcmp(el, "cmt") == 0) { in_cmt++; } - else if (strcmp(el, "rtept") == 0) { + else if (strcmp(el, "rte") == 0) { + rte_head = route_head_alloc(); + route_add_head(rte_head); in_rte++; + } + else if (strcmp(el, "rtept") == 0) { + in_rtept++; tag_wpt(attr); } else if (strcmp(el, "trk") == 0) { @@ -508,6 +515,24 @@ gpx_end(void *data, const char *el) if (in_number && in_trk) { trk_head->rte_num = atoi(cdatastr); } + if (in_name && in_rte && ! in_rtept) { + rte_head->rte_name = xstrdup(cdatastr); + } + if (in_desc && in_rte && ! in_rtept ) { + rte_head->rte_desc = xstrdup(cdatastr); + } + if (in_number && in_rte) { + rte_head->rte_num = atoi(cdatastr); + } + if (in_name && in_rtept) { + wpt_tmp->shortname = xstrdup(cdatastr); + } + if (in_desc && in_rtept) { + wpt_tmp->notes = xstrdup(cdatastr); + } + if (in_cmt && in_rtept) { + wpt_tmp->description = xstrdup(cdatastr); + } if (gsshortnames) { if (in_gs_name && in_wpt && !in_gs_tbugs) { wpt_tmp->notes = xstrdup(cdatastr); @@ -517,7 +542,7 @@ gpx_end(void *data, const char *el) wpt_tmp->notes = xstrdup(cdatastr); } } - if (in_cmt && in_wpt) { + if ((in_cmt && in_wpt) || (in_cmt && in_rtept)) { wpt_tmp->description = xstrdup(cdatastr); } if (in_url && in_wpt) { @@ -526,7 +551,7 @@ gpx_end(void *data, const char *el) if (in_urlname && in_wpt) { wpt_tmp->url_link_text = xstrdup(cdatastr); } - if (in_icon && in_wpt) { + if ((in_icon && in_wpt) || (in_icon && in_rtept)) { wpt_tmp->icon_descr = xstrdup(cdatastr); wpt_tmp->icon_descr_is_dynamic = 1; } @@ -535,7 +560,7 @@ gpx_end(void *data, const char *el) &wpt_tmp->position.altitude.altitude_meters); } if (in_time) { - if ( in_wpt || in_rte || in_trkpt) { + if ( in_wpt || in_rte || in_trkpt || in_rtept) { wpt_tmp->creation_time = xml_parse_time( cdatastr ); } @@ -570,10 +595,12 @@ gpx_end(void *data, const char *el) waypt_add(wpt_tmp); in_wpt--; logpoint_ct = 0; - } - else if (strcmp(el, "rtept") == 0) { -/* route_add(wpt_tmp); */ + } + else if (strcmp(el, "rte") == 0) { in_rte--; + } else if (strcmp(el, "rtept") == 0) { + route_add_wpt(rte_head, wpt_tmp); + in_rtept--; } else if (strcmp(el, "trk") == 0) { in_trk--; } else if (strcmp(el, "trkpt") == 0) { @@ -664,6 +691,11 @@ gpx_cdata(void *dta, const XML_Char *s, int len) (in_trk && in_name) || (in_trk && in_desc) || (in_trk && in_number) || + (in_rte && in_cmt) || + (in_rte && in_name) || + (in_rte && in_desc) || + (in_rte && in_icon) || + (in_rte && in_number) || (in_time)) { estr = cdatastr + strlen(cdatastr); memcpy(estr, s, len); @@ -965,6 +997,83 @@ void gpx_track_pr() route_disp_all(gpx_track_hdr, gpx_track_tlr, gpx_track_disp); } +static void +gpx_route_hdr(const route_head *rte) +{ + char * tmp_ent; + + fprintf(ofd, "\n"); + if (rte->rte_name) { + tmp_ent = gpx_entitize(rte->rte_name); + fprintf(ofd, "%s\n", tmp_ent); + xfree(tmp_ent); + } + if (rte->rte_desc) { + tmp_ent = gpx_entitize(rte->rte_desc); + fprintf(ofd, "%s\n", tmp_ent); + xfree(tmp_ent); + } + if (rte->rte_num) { + fprintf(ofd, "%d\n", rte->rte_num); + } +} + +static void +gpx_route_disp(const waypoint *waypointp) +{ + fprintf(ofd, "\n", + waypointp->position.latitude.degrees, + waypointp->position.longitude.degrees); + + if (waypointp->position.altitude.altitude_meters != unknown_alt) { + fprintf(ofd, "%f\n", + waypointp->position.altitude.altitude_meters); + } + if (waypointp->creation_time) { + gpx_write_time(waypointp->creation_time,"time"); + } + if (waypointp->shortname) { + fprintf(ofd, ""); + fprintf(ofd, "", waypointp->shortname); + fprintf(ofd, "\n"); + } + if (waypointp->description) { + fprintf(ofd, ""); + fprintf(ofd, "", waypointp->description); + fprintf(ofd, "\n"); + } + if (waypointp->notes) { + fprintf(ofd, ""); + fprintf(ofd, "", waypointp->notes); + fprintf(ofd, "\n"); + } + if (waypointp->icon_descr) { + fprintf(ofd, ""); + fprintf(ofd, "", waypointp->icon_descr); + fprintf(ofd, ""); + } + + fprintf(ofd, "\n"); +} + +static void +gpx_route_tlr(const route_head *rte) +{ + fprintf(ofd, "\n"); +} + +static +void gpx_noop() +{ +} + +static +void gpx_route_pr() +{ + /* output routes */ + route_disp_all(gpx_route_hdr, gpx_route_tlr, gpx_route_disp); +} + void gpx_write(void) { @@ -982,9 +1091,15 @@ gpx_write(void) gpx_write_time( now, "time" ); switch(global_opts.objective) { - case trkdata: gpx_track_pr(); - case wptdata: waypt_disp_all(gpx_waypt_pr); - break; + case trkdata: + gpx_track_pr(); + break; + case rtedata: + gpx_route_pr(); + break; + case wptdata: + waypt_disp_all(gpx_waypt_pr); + break; default: break; } diff --git a/gpsbabel/magellan.h b/gpsbabel/magellan.h index 7050befbe..f7a023b16 100644 --- a/gpsbabel/magellan.h +++ b/gpsbabel/magellan.h @@ -48,3 +48,4 @@ const char * mag_find_descr_from_token(const char *token); const char * mag_find_token_from_descr(const char *icon); waypoint * mag_trkparse(char *trkmsg); +void mag_rteparse(char *rtemsg); diff --git a/gpsbabel/magproto.c b/gpsbabel/magproto.c index e9a57e93d..9fe5c3e2e 100644 --- a/gpsbabel/magproto.c +++ b/gpsbabel/magproto.c @@ -67,6 +67,8 @@ typedef struct mag_rte_head { int nelems; } mag_rte_head; +static queue rte_wpt_tmp; /* temporary PGMNWPL msgs for routes */ + static FILE *magfile_in; static FILE *magfile_out; static int magfd; @@ -169,7 +171,6 @@ pid_to_model_t pid_to_model[] = static icon_mapping_t *icon_mapping = map330_icon_table; - /* * For each receiver type, return a "cleansed" version of the string * that's valid for a waypoint name or comment. The string should be @@ -419,12 +420,25 @@ retry: } if (strncmp(ibuf, "$PMGNWPT,", 7) == 0) { waypoint *wpt = mag_wptparse(ibuf); - waypt_add(wpt); - } + switch (global_opts.objective) + { + case wptdata: + waypt_add(wpt); + break; + case rtedata: + ENQUEUE_TAIL(&rte_wpt_tmp, &wpt->Q); + break; + default: + break; + } + } if (strncmp(ibuf, "$PMGNTRK,", 7) == 0) { waypoint *wpt = mag_trkparse(ibuf); route_add_wpt(trk_head, wpt); - } + } + if (strncmp(ibuf, "$PMGNRTE,", 7) == 0) { + mag_rteparse(ibuf); + } if (IS_TKN("$PMGNVER,")) { mag_verparse(ibuf); } @@ -716,6 +730,8 @@ mag_rd_init(const char *portname, const char *args) mag_writemsg("PMGNCMD,NMEAOFF"); } + QUEUE_INIT(&rte_wpt_tmp); + return; } @@ -760,6 +776,7 @@ mag_wr_init(const char *portname, const char *args) #endif mag_rd_init(portname, args); } + QUEUE_INIT(&rte_wpt_tmp); } static void @@ -773,6 +790,8 @@ mag_deinit(void) if(mkshort_handle) mkshort_del_handle(mkshort_handle); mkshort_handle = NULL; + + waypt_flush(&rte_wpt_tmp); } @@ -834,7 +853,7 @@ mag_trkparse(char *trkmsg) * $PMGNRTE,4,1,c,1,DAD,a,Anna,a*61 * generate a route. */ -waypoint * +void mag_rteparse(char *rtemsg) { char descr[100]; @@ -844,7 +863,8 @@ mag_rteparse(char *rtemsg) char *currtemsg; static mag_rte_head *mag_rte_head; mag_rte_elem *rte_elem; - + char *p; + descr[0] = 0; sscanf(rtemsg,"$PMGNRTE,%d,%d,%c,%d%n", @@ -852,9 +872,7 @@ mag_rteparse(char *rtemsg) /* * This is the first component of a route. Allocate a new - * queue head. It's kind of unfortunate that we can't know - * a priori how many items are on this track, so we have to - * alloc and chain those as we go. + * queue head. */ if (frag == 1) { mag_rte_head = xcalloc(sizeof (*mag_rte_head),1); @@ -869,13 +887,20 @@ mag_rteparse(char *rtemsg) * loop and pick those up. */ while (sscanf(currtemsg,",%[^,],%[^,]%n",next_stop, abuf,&n)) { - if (next_stop[0] == 0) { + if ((next_stop[0] == 0) || (next_stop[0] == '*')) { break; } + + /* trim CRC from waypoint icon string */ + if ((p = strchr(abuf, '*')) != NULL) + *p = '\0'; + rte_elem = xcalloc(sizeof (*rte_elem),1); QUEUE_INIT(&rte_elem->Q); + rte_elem->wpt_name = xstrdup(next_stop); rte_elem->wpt_icon = xstrdup(abuf); + ENQUEUE_TAIL(&mag_rte_head->Q, &rte_elem->Q); next_stop[0] = 0; currtemsg += n; @@ -891,28 +916,38 @@ mag_rteparse(char *rtemsg) rte_head = route_head_alloc(); route_add_head(rte_head); + rte_head->rte_num = rtenum; - /* - * TODO: I suppose we have to fetch the waypoints to - * get the underlying data for each stop in the route. + /* + * It is quite feasible that we have 200 waypoints, + * 3 of which are used in the route. We'll need to find + * those in the queue for SD routes... */ + QUEUE_FOR_EACH(&mag_rte_head->Q, elem, tmp) { - static int lat; /* Dummy data */ mag_rte_elem *re = (mag_rte_elem *) elem; waypoint *waypt; + queue *welem, *wtmp; - waypt = xcalloc(sizeof *waypt, 1); - - /* TODO Populate rest of waypoint. */ - waypt->shortname = re->wpt_name; - waypt->position.latitude.degrees = ++lat; + /* + * Copy route points from temp wpt queue. + */ + QUEUE_FOR_EACH(&rte_wpt_tmp, welem, wtmp) { + waypt = (waypoint *)welem; + if (strcmp(waypt->shortname, re->wpt_name) == 0) { + waypoint * wpt = waypt_dupe(waypt); + route_add_wpt(rte_head, wpt); + break; + } + } - route_add_wpt(rte_head, waypt); dequeue(&re->Q); + xfree(re->wpt_name); + xfree(re->wpt_icon); xfree(re); } + xfree(mag_rte_head); } - return 0; } const char * @@ -1003,7 +1038,8 @@ mag_wptparse(char *trkmsg) for (blah = icons ; blah < icone; blah++) icon_token[i++] = *blah; - + icon_token[i++] = '\0'; + if (latdir == 'S') latdeg = -latdeg; waypt->position.latitude.degrees = mag2degrees(latdeg); @@ -1021,6 +1057,8 @@ mag_wptparse(char *trkmsg) static void mag_read(void) { + found_done = 0; + switch (global_opts.objective) { case trkdata: @@ -1030,17 +1068,51 @@ mag_read(void) if (!is_file) mag_writemsg("PMGNCMD,TRACK,2"); + while (!found_done) { + mag_readmsg(); + } + break; case wptdata: if (!is_file) mag_writemsg("PMGNCMD,WAYPOINT"); + + while (!found_done) { + mag_readmsg(); + } + break; - default: - fatal(MYNAME ": Routes are not yet supported\n"); - } + case rtedata: + if (!is_file) { + /* + * serial routes require waypoint & routes + * messages commands. + */ + mag_writemsg("PMGNCMD,WAYPOINT"); - while (!found_done) { - mag_readmsg(); + while (!found_done) { + mag_readmsg(); + } + + mag_writemsg("PMGNCMD,ROUTE"); + + found_done = 0; + while (!found_done) { + mag_readmsg(); + } + } else { + /* + * SD routes are a stream of PMGNWPL and + * PMGNRTE messages, in that order. + */ + while (!found_done) { + mag_readmsg(); + } + } + + break; + default: + fatal(MYNAME ": Unknown objective\n"); } } @@ -1169,6 +1241,80 @@ void mag_track_pr() route_disp_all(mag_track_nop, mag_track_nop, mag_track_disp); } +/* +The spec says to stack points: + $PMGNRTE,2,1,c,1,FOO,POINT1,b,POINT2,c,POINT3,d*6C + +Meridian SD card and serial (at least) writes in pairs: + $PMGNRTE,4,1,c,1,HOME,c,I49X73,a*15 + ... + $PMGNRTE,4,4,c,1,RON273,a,MYCF93,a*7B + +The spec also says that some units don't like single-legged pairs, +and to replace the 2nd name with "<<>>", but I haven't seen one of those. +*/ + +static void +mag_route_trl(const route_head * rte) +{ + queue *elem, *tmp; + waypoint *waypointp; + char obuff[256]; + char buff1[64], buff2[64]; + char *pbuff; + const char * icon_token; + int i, numlines, thisline; + + /* count waypoints for this route */ + i = rte->rte_waypt_ct; + + /* number of output PMGNRTE messages at 2 points per line */ + numlines = (i / 2) + (i % 2); + + thisline = i = 0; + QUEUE_FOR_EACH(&rte->waypoint_list, elem, tmp) { + waypointp = (waypoint *) elem; + i++; + + if (deficon) + icon_token = mag_find_token_from_descr(deficon); + else + icon_token = mag_find_token_from_descr(waypointp->icon_descr); + + if (i == 1) + pbuff = buff1; + else + pbuff = buff2; + + sprintf(pbuff, "%s,%s", waypointp->shortname, icon_token); + + if ((tmp == &rte->waypoint_list) || ((i % 2) == 0)) { + thisline++; + + sprintf(obuff, "PMGNRTE,%d,%d,c,%d,%s,%s", + numlines, thisline, rte->rte_num, + buff1, buff2); + + mag_writemsg(obuff); + buff1[0] = '\0'; + buff2[0] = '\0'; + i = 0; + } + } +} + +static void +mag_route_hdr() +{ +} + +static void +mag_route_pr() +{ + route_disp_all(mag_route_hdr, mag_route_trl, mag_waypt_pr); + +} + static void mag_write(void) { @@ -1185,8 +1331,11 @@ mag_write(void) case wptdata: waypt_disp_all(mag_waypt_pr); break; + case rtedata: + mag_route_pr(); + break; default: - fatal(MYNAME ": Routes are not yet supported\n"); + fatal(MYNAME ": Unknown objective.\n"); } } diff --git a/gpsbabel/mapsend.c b/gpsbabel/mapsend.c index 78af2c006..dcd16f855 100644 --- a/gpsbabel/mapsend.c +++ b/gpsbabel/mapsend.c @@ -32,6 +32,8 @@ static void *mkshort_handle; static int endianness_tested; static int i_am_little_endian; +static int route_wp_count; + #define MYNAME "mapsend" static void @@ -174,6 +176,7 @@ mapsend_wr_init(const char *fname, const char *args) exit(1); } mkshort_handle = mkshort_new_handle(); + route_wp_count = 0; } static void @@ -190,7 +193,7 @@ mapsend_wpt_read(void) char name[257]; char comment[257]; char *p; - int wpt_count; + int wpt_count, rte_count, rte_num; unsigned char scount; int wpt_number; char wpt_icon; @@ -199,8 +202,10 @@ mapsend_wpt_read(void) double wpt_long; double wpt_lat; waypoint *wpt_tmp; - my_fread4(&wpt_count, mapsend_file_in); + route_head *rte_head; + my_fread4(&wpt_count, mapsend_file_in); + while (wpt_count--) { wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); @@ -238,6 +243,55 @@ mapsend_wpt_read(void) waypt_add(wpt_tmp); } + + /* now read the routes... */ + my_fread4(&rte_count, mapsend_file_in); + + while (rte_count--) { + rte_head = route_head_alloc(); + route_add_head(rte_head); + + /* route name */ + fread(&scount, sizeof(scount), 1, mapsend_file_in); + fread(tbuf, scount, 1, mapsend_file_in); + tbuf[scount] = '\0'; + rte_head->rte_name = xstrdup(tbuf); + + /* route # */ + my_fread4(&rte_num, mapsend_file_in); + rte_head->rte_num = rte_num; + + /* points this route */ + my_fread4(&wpt_count, mapsend_file_in); + + while (wpt_count--) { + wpt_tmp = xcalloc(sizeof(*wpt_tmp), 1); + + /* waypoint name */ + fread(&scount, sizeof(scount), 1, mapsend_file_in); + fread(tbuf, scount, 1, mapsend_file_in); + tbuf[scount] = '\0'; + + wpt_tmp->shortname = xstrdup(tbuf); + + /* waypoint # */ + my_fread4(&wpt_number, mapsend_file_in); + my_fread8(&wpt_long, mapsend_file_in); + my_fread8(&wpt_lat, mapsend_file_in); + fread(&wpt_icon, sizeof(wpt_icon), 1, mapsend_file_in); + + wpt_tmp->position.longitude.degrees = wpt_long; + wpt_tmp->position.latitude.degrees = -wpt_lat; + + if (wpt_icon < 26) + sprintf(tbuf, "%c", wpt_icon + 'a'); + else + sprintf(tbuf, "a%c", wpt_icon - 26 + 'a'); + wpt_tmp->icon_descr = mag_find_descr_from_token(tbuf); + + route_add_wpt(rte_head, wpt_tmp); + } + } } static void @@ -354,6 +408,7 @@ n = ++cnt; } fwrite(&n, 1, 1, mapsend_file_out); n = 1; + fwrite(&n, 1, 1, mapsend_file_out); falt = waypointp->position.altitude.altitude_meters; @@ -365,20 +420,108 @@ n = 1; my_fwrite8(&flat, mapsend_file_out); } -void +static void +mapsend_route_hdr(const route_head *rte) +{ + int wp_ct; + unsigned char c; + char * rname; + + /* route name -- mapsend really seems to want something here.. */ + if (!rte->rte_name) + rname = xstrdup("Route"); + else + rname = xstrdup(rte->rte_name); + + c = strlen(rname); + + fwrite(&c, 1, 1, mapsend_file_out); + fwrite(rname, c, 1, mapsend_file_out); + + xfree(rname); + + /* route # */ + c = rte->rte_num; + my_fwrite4(&c, mapsend_file_out); + + wp_ct = rte->rte_waypt_ct; + + /* # of waypoints to follow... */ + my_fwrite4(&wp_ct, mapsend_file_out); +} + +static void +mapsend_noop() +{ + /* no-op */ +} + +static void +mapsend_route_disp(const waypoint *waypointp) +{ + unsigned char c; + const char *iconp; + double dbl; + int n; + + route_wp_count++; + + /* waypoint name */ + c = strlen(waypointp->shortname); + fwrite(&c, 1, 1, mapsend_file_out); + fwrite(waypointp->shortname, c, 1, mapsend_file_out); + + /* waypoint number */ + my_fwrite4(&route_wp_count, mapsend_file_out); + + dbl = waypointp->position.longitude.degrees; + my_fwrite8(&dbl, mapsend_file_out); + + dbl = -waypointp->position.latitude.degrees; + my_fwrite8(&dbl, mapsend_file_out); + + if (waypointp->icon_descr) { + iconp = mag_find_token_from_descr(waypointp->icon_descr); + if (1 == strlen(iconp)) { + n = iconp[0] - 'a'; + } else { + n = iconp[1] - 'a' + 26; + } + } else { + n = 0; + } + fwrite(&n, 1, 1, mapsend_file_out); +} + +static void mapsend_wpt_write(void) { mapsend_hdr hdr = {13, "4D533330 MS", "30", ms_type_wpt, 0}; int wpt_count = waypt_count(); int n = 0; - + fwrite(&hdr, sizeof(hdr), 1, mapsend_file_out); - my_fwrite4(&wpt_count, mapsend_file_out); - waypt_disp_all(mapsend_waypt_pr); + if (global_opts.objective == wptdata) { + my_fwrite4(&wpt_count, mapsend_file_out); + waypt_disp_all(mapsend_waypt_pr); + } else + if (global_opts.objective == rtedata) { + + /* # of points - all routes */ + n = route_waypt_count(); + my_fwrite4(&n, mapsend_file_out); + + /* write points - all routes */ + route_disp_all(mapsend_noop, mapsend_noop, mapsend_waypt_pr); + } + + n = route_count(); my_fwrite4(&n, mapsend_file_out); -/* TODO: Implement routes here */ + + if (n) + route_disp_all(mapsend_route_hdr, mapsend_noop, mapsend_route_disp); } #if LATER diff --git a/gpsbabel/reference/route/magellan.rte b/gpsbabel/reference/route/magellan.rte new file mode 100644 index 000000000..d7b9b55d1 --- /dev/null +++ b/gpsbabel/reference/route/magellan.rte @@ -0,0 +1,22 @@ +$PMGNWPL,3042.000,N,09224.000,W,0000000,M,49B,,a*01 +$PMGNWPL,3012.000,N,09218.000,W,0000000,M,49A,,a*08 +$PMGNWPL,2924.000,N,09212.000,W,0000000,M,48B,,a*0D +$PMGNWPL,2900.000,N,09154.000,W,0000000,M,48A,,a*09 +$PMGNWPL,2824.000,N,09124.000,W,0000000,M,47B,,a*05 +$PMGNWPL,2748.000,N,09106.000,W,0000000,M,47A,,a*03 +$PMGNWPL,2636.000,N,09018.000,W,0000000,M,46A,,a*04 +$PMGNWPL,2424.000,N,08824.000,W,0000000,M,43A,,a*06 +$PMGNWPL,2336.000,N,08712.000,W,0000000,M,42A,,a*09 +$PMGNWPL,2300.000,N,08536.000,W,0000000,M,41A,,a*0B +$PMGNWPL,2218.000,N,08424.000,W,0000000,M,40A,,a*00 +$PMGNRTE,6,1,c,0,49B,a,49A,a*00 +$PMGNRTE,6,2,c,0,48B,a,48A,a*03 +$PMGNRTE,6,3,c,0,47B,a,47A,a*02 +$PMGNRTE,6,4,c,0,46A,a,43A,a*03 +$PMGNRTE,6,5,c,0,42A,a,41A,a*04 +$PMGNRTE,6,6,c,0,40A,a,*0C +$PMGNWPL,3016.831,N,09141.153,W,0000000,M,ATLAUN,Launch at Butte LaRose,i*15 +$PMGNWPL,3017.463,N,09137.630,W,0000000,M,ATWRNC,Canal to Warner Lake,k*38 +$PMGNWPL,3018.883,N,09138.767,W,0000000,M,ATWRNR,Warner Lake,a*78 +$PMGNRTE,2,1,c,1,ATLAUN,i,ATWRNC,k*1A +$PMGNRTE,2,2,c,1,ATWRNR,a,*44 diff --git a/gpsbabel/reference/route/route.gpx b/gpsbabel/reference/route/route.gpx new file mode 100644 index 000000000..b8d58a158 --- /dev/null +++ b/gpsbabel/reference/route/route.gpx @@ -0,0 +1,77 @@ + + + + +LILI PATH +Hurricane LILI + +0.000000 + + + +0.000000 + + + +0.000000 + + + +0.000000 + + + +0.000000 + + + +0.000000 + + + +0.000000 + + + +0.000000 + + + +0.000000 + + + +0.000000 + + + +0.000000 + + + + +ATCHAFALAYA +ROUTE1 +1 + +0.000000 + + + + +0.000000 + + + + +0.000000 + + + + + diff --git a/gpsbabel/reference/route/route.mapsend b/gpsbabel/reference/route/route.mapsend new file mode 100644 index 0000000000000000000000000000000000000000..2fd785eb1d4caf57695202d2f6d3b79430b21b5c GIT binary patch literal 922 zcmZ9L%`QVh6vq#x+R|<$!bT)s;Bu?2ug19*pO;AW-li|$8Q2I`wqnJ~J6PDxN-Qdt z;sGSY#!83<=Rb34XC`Sgo&T@r%*^lJd~tckm*Gup?fPC15f$W5s-2~{g~?wVWN?z zIH|G#geh$yy8dmfbi?+%ASI>&3(?y>kCm==F(-)6l(7(V=)Xo4L8h6q7GfGiNtLo7 zQ%pGvF^7#57Kwm(OoN!)CmM^)cEgfNb0g$vn}!6+{8I<}5691Mv3mRrKOR=ApqlmV z8s&w`{Zp;e!tvxwtcpiBOD7wDR9%bhbbKEj|8Bj;>h5r4^K7T8pfVe-hwBqN+*qTl z?;q?C4+09Ci|E)#!1#;nT!Kmf=dNi44AZ()mtP6W0sQKq%PInfRoA5iC5B7apaed{ zpzBS7X@)n~mIPA_TdpGsJjM-}QXMli$c@?>uW-mM?vZQ4VG~`jQ); QUEUE_INIT(&rte->waypoint_list); + rte_head_ct++; } void route_add_wpt(route_head *rte, waypoint *wpt) { ENQUEUE_TAIL(&rte->waypoint_list, &wpt->Q); + rte->rte_waypt_ct++; /* waypoints in this route */ + rte_waypts++; /* total waypoints in all routes */ } void diff --git a/gpsbabel/testo b/gpsbabel/testo index 752a33d9c..624032c38 100755 --- a/gpsbabel/testo +++ b/gpsbabel/testo @@ -238,3 +238,30 @@ ${PNAME} -i geo -f geocaching.loc -o csv -F ${TMPDIR}/filterpos.csv1 ${PNAME} -i geo -f geocaching.loc -f geocaching.loc -x position,distance=5f \ -o csv -F ${TMPDIR}/filterpos.csv2 compare ${TMPDIR}/filterpos.csv1 ${TMPDIR}/filterpos.csv2 + +# +# magellan SD card waypoint / route format +# +rm -f ${TMPDIR}/magellan.rte +${PNAME} -r -i magellan -f reference/route/magellan.rte -o magellan \ + -F ${TMPDIR}/magellan.rte +compare ${TMPDIR}/magellan.rte reference/route/magellan.rte + +# +# GPX routes -- since GPX contains a date stamp, tests will always +# fail, so we use magellan as an interim format... +# +rm -f ${TMPDIR}/gpxroute.gpx ${TMPDIR}/maggpx.rte +${PNAME} -r -i gpx -f reference/route/route.gpx -o gpx \ + -F ${TMPDIR}/gpxroute.gpx +${PNAME} -r -i gpx -f ${TMPDIR}/gpxroute.gpx -o magellan \ + -F ${TMPDIR}/maggpx.rte +compare ${TMPDIR}/maggpx.rte reference/route/magellan.rte + +# +# MAPSEND waypoint / route format +# +rm -f ${TMPDIR}/route.mapsend +${PNAME} -r -i mapsend -f reference/route/route.mapsend -o mapsend \ + -F ${TMPDIR}/route.mapsend +compare ${TMPDIR}/route.mapsend reference/route/ diff --git a/gpsbabel/waypt.c b/gpsbabel/waypt.c index 2ca9c6bad..9a5db5e74 100644 --- a/gpsbabel/waypt.c +++ b/gpsbabel/waypt.c @@ -33,6 +33,26 @@ waypt_init(void) QUEUE_INIT(&waypt_head); } +waypoint * +waypt_dupe(waypoint *wpt) +{ + waypoint * tmp; + tmp = xcalloc(sizeof *wpt, 1); + memcpy(tmp, wpt, sizeof(waypoint)); + + if (wpt->shortname) + tmp->shortname = xstrdup(wpt->shortname); + if (wpt->description) + tmp->description = xstrdup(wpt->description); + if (wpt->notes) + tmp->notes = xstrdup(wpt->notes); + if (wpt->url) + tmp->url = xstrdup(wpt->url); + if (wpt->url_link_text) + tmp->url_link_text = xstrdup(wpt->url_link_text); + + return tmp; +} void waypt_add(waypoint *wpt) { -- 2.30.2